package com.eastfair.venueservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.StrUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.auth.vo.UserAccountVo;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.builder.dto.ExhibitorDTO;
import com.eastfair.builder.vo.ExhibitorVO;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.encrypt.RSAEncrypt;
import com.eastfair.core.exception.BizException;
import com.eastfair.database.mybatis.typehandler.M9EncryptHandler;
import com.eastfair.database.mybatis.typehandler.TypeHandlerUtil;
import com.eastfair.venueservice.consts.CommonConstants;
import com.eastfair.venueservice.dao.ServiceProviderMapper;
import com.eastfair.venueservice.dto.ServiceProviderAuditDTO;
import com.eastfair.venueservice.dto.ServiceProviderDTO;
import com.eastfair.venueservice.dto.ServiceProviderUserDTO;
import com.eastfair.venueservice.entity.CreatCode;
import com.eastfair.venueservice.entity.ServiceProvider;
import com.eastfair.venueservice.entity.ServiceProviderAudit;
import com.eastfair.venueservice.entity.ServiceProviderUser;
import com.eastfair.venueservice.enumeration.ServiceItemAuditStateEnum;
import com.eastfair.venueservice.enumeration.ServiceProviderAuditStatusEnum;
import com.eastfair.venueservice.enumeration.ServiceProviderRoleEnum;
import com.eastfair.venueservice.exceptioncode.VenueServiceExceptionCode;
import com.eastfair.venueservice.service.*;
import com.eastfair.venueservice.vo.ExhibitionServiceProviderVO;
import com.eastfair.venueservice.vo.ServiceProviderSpaceVO;
import com.eastfair.venueservice.vo.ServiceProviderVO;
import com.eastfair.venueservice.vo.ViolationRecordVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 服务商信息表
 * </p>
 *
 * @author gj
 * @date 2022 -07-13
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class ServiceProviderServiceImpl extends SuperServiceImpl<ServiceProviderMapper, ServiceProvider> implements ServiceProviderService {

    private static final String COMPANY_CODE_PREFIX = "BU";

    private static final String COMPANY_CODE_FIELD = "company_code";

    private static final int COMPANY_CODE_LENGTH = 7;

    @Resource
    private ServiceProviderAuditService serviceProviderAuditService;

    @Resource
    private ServiceProviderUserService serviceProviderUserService;

    @Resource
    private ExhibitionServiceProviderService exhibitionServiceProviderService;

    @Resource
    private VenueManageMatchingRegisterService venueManageMatchingRegisterService;

    @Resource
    private VenueManageHomeRegisterService venueManageHomeRegisterService;

    @Resource
    private VenueManageBuilderRegisterService venueManageBuilderRegisterService;

    @Resource
    private VenueManageTransportRegisterService venueManageTransportRegisterService;

    @Resource
    private VenueManageUserAccountService venueManageUserAccountService;

    @Resource
    private VenueManageExhibitorService venueManageExhibitorService;

    @Resource
    private ServiceProviderMapper serviceProviderMapper;
    @Resource
    private EvaluateComplaintService evaluateComplaintService;
    @Resource
    private ViolationRecordService violationRecordService;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<ServiceProvider> modelList) {
        modelList.forEach(s -> s.setIsDeleted(BusinessConstant.YES));
        return R.successDef();
    }

    @Override
    protected R<Boolean> handlerSave(ServiceProvider model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        if (model.getAuditStatus() == null) {
            model.setAuditStatus(ServiceProviderAuditStatusEnum.REPORTING);
        }
        if (model.getRegisterTime() == null) {
            model.setRegisterTime(LocalDateTime.now());
        }
        return R.successDef();
    }

    @Override
    public IPage<ServiceProviderVO> listServiceProviderVOs(PageParams<ServiceProviderDTO> pageParams) {
        log.info("listServiceProviderVOs - 分页查询服务商列表VO, pageParams={}", pageParams);
        ServiceProviderDTO query = pageParams.getModel();
        QueryWrapper<ServiceProvider> queryWrapper = createServiceProviderVOQueryWrapper(query);
        Page<ServiceProvider> page = pageParams.buildPage();
        IPage<ServiceProviderVO> serviceProviderVOIPage = serviceProviderMapper.listServiceProviderVOs(page, queryWrapper);
        for (ServiceProviderVO record : serviceProviderVOIPage.getRecords()) {
            try {
                record.setLegalMobile(TypeHandlerUtil.decrypt(record.getLegalMobile()));
                record.setPrincipalMobile(TypeHandlerUtil.decrypt(record.getPrincipalMobile()));
            }catch (Exception e){
                log.warn("解密失败:{}",record);
            }
        }
        return serviceProviderVOIPage;
    }

    @Override
    public List<ServiceProviderVO> listServiceProviderVOs(ServiceProviderDTO query) {
        log.info("listServiceProviderVOs - 查询服务商列表VO, query={}", query);
        List<ServiceProvider> list = listServiceProviders(query);
        if (list == null || list.isEmpty()) {
            return Collections.emptyList();
        }
        return list
                .stream()
                .map(serviceProvider -> BeanUtil.toBean(serviceProvider, ServiceProviderVO.class))
                .collect(Collectors.toList());
    }

    /**
     * cms同步查询服务商列表
     *
     * @return
     */
    @Override
    public List<ServiceProviderVO> queryCrmSyncServiceProvider() {
        log.info("queryCrmSyncServiceProvider - 查询待同步cms的服务商");
        QueryWrapper<ServiceProvider> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(ServiceProvider::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(ServiceProvider::getCmsSync, BusinessConstant.NO)
                .orderByAsc(ServiceProvider::getUpdateTime)
                .last("limit 10")
        ;
        List<ServiceProvider> list = list(queryWrapper);
        if (list == null || list.isEmpty()) {
            return Collections.emptyList();
        }

        return list
                .stream()
                .map(serviceProvider -> BeanUtil.toBean(serviceProvider, ServiceProviderVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public List<ServiceProvider> listServiceProviders(ServiceProviderDTO query) {
        log.info("listServiceProviders - 查询服务商列表, query={}", query);
        QueryWrapper<ServiceProvider> queryWrapper = createServiceProviderQueryWrapper(query);
        return list(queryWrapper);
    }

    @Override
    public List<ServiceProviderVO> listServiceProviderByIds(List<Long> ids) {
        log.info("listServiceProviderByIds - ID列表获取服务商列表, ids={}", ids);
        ServiceProviderDTO query = new ServiceProviderDTO();
        query.setIds(ids);
        List<ServiceProvider> list = listServiceProviders(query);
        return list
                .stream()
                .map(serviceProvider -> BeanUtil.toBean(serviceProvider, ServiceProviderVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public List<ServiceProvider> listWaitingDisableServiceProviders(String serviceProviderType) {
        log.info("listWaitingDisableServiceProviders - 查询待失效服务商列表, serviceProviderType={}", serviceProviderType);
        LocalDateTime now = LocalDateTime.now();
        QueryWrapper<ServiceProvider> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .isNotNull(ServiceProvider::getValidStartTime)
                .isNotNull(ServiceProvider::getValidEndTime)
                .lt(ServiceProvider::getValidEndTime, now)
                .eq(ServiceProvider::getAuditStatus, ServiceItemAuditStateEnum.APPROVED)
                .eq(ServiceProvider::getIsEnabled, BusinessConstant.ENABLE_YES)
                .eq(StrUtil.isNotBlank(serviceProviderType), ServiceProvider::getServiceProviderType, serviceProviderType)
        ;
        return list(queryWrapper);
    }

    @Override
    public List<ExhibitorVO> listBuilderByHomeId(Long homeId, Long exhibitionId) {
        log.info("listBuilderByHomeId - 主场查询负责的搭建商, homeId={}, exhibitionId={}", homeId, exhibitionId);
        // 查询展会负责的该主场，以及主场负责的展厅
        List<ServiceProviderVO> homeList = exhibitionServiceProviderService.listVOByExhibitionManageId(exhibitionId, homeId);
        if (homeList == null || homeList.isEmpty()) {
            return Collections.emptyList();
        }
        ServiceProviderVO homeVO = homeList.get(0);
        List<ServiceProviderSpaceVO> serviceProviderSpaceList = homeVO.getServiceProviderSpaces();
        if (serviceProviderSpaceList == null || serviceProviderSpaceList.isEmpty()) {
            return Collections.emptyList();
        }
        List<String> spaceCodeList = serviceProviderSpaceList
                .stream()
                .map(ServiceProviderSpaceVO::getSpaceCode)
                .collect(Collectors.toList());
        // 通过展会ID，展厅列表查询展商列表
        ExhibitorDTO exhibitorDTO = new ExhibitorDTO();
        exhibitorDTO.setExhibitionManageId(exhibitionId);
        exhibitorDTO.setSpaceCodeList(spaceCodeList);
        return venueManageExhibitorService.queryExhibitors(exhibitorDTO);
    }

    @Override
    public ServiceProvider getServiceProvider(ServiceProviderDTO query) {
        QueryWrapper<ServiceProvider> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .last("limit 1")
                .eq(ServiceProvider::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(query.getIsEnabled() != null, ServiceProvider::getIsEnabled, query.getIsEnabled())
                .eq(StrUtil.isNotBlank(query.getServiceProviderType()), ServiceProvider::getServiceProviderType, query.getServiceProviderType())
                .eq(query.getUserId() != null, ServiceProvider::getUserId, query.getUserId())
                .eq(StrUtil.isNotBlank(query.getCompanyName()), ServiceProvider::getCompanyName, query.getCompanyName())
                .eq(StrUtil.isNotBlank(query.getUscc()), ServiceProvider::getUscc, query.getUscc())
                .eq(query.getIsUserFirstRegister() != null, ServiceProvider::getIsUserFirstRegister, query.getIsUserFirstRegister())
        ;
        return getOne(queryWrapper);
    }

    @Override
    public ServiceProvider getByUserId(Long userId, String serviceProviderType) {
        log.info("getServiceProviderByUserId - 用户ID，服务商类型 查询服务商注册信息, userId={}, serviceProviderType={}",
                userId, serviceProviderType);
        ServiceProviderUser serviceProviderUser = serviceProviderUserService.getByUserId(userId, serviceProviderType);
        if (serviceProviderUser == null) {
            return null;
        }
        return getById(serviceProviderUser.getServiceProviderId());
    }

    @Override
    public ServiceProvider getFirstRegisterByUserId(Long userId) {
        log.info("getFirstRegisterByUserId - 获取用户注册的首个服务商, userId={}", userId);
        ServiceProviderUser serviceProviderUser = serviceProviderUserService.getFirstRegisterMainByUserId(userId);
        if (serviceProviderUser == null) {
            return null;
        }
        ServiceProvider serviceProvider = getById(serviceProviderUser.getServiceProviderId());
        serviceProvider.setUserId(serviceProviderUser.getUserId());
        return serviceProvider;
    }

    @Override
    public ServiceProvider getByCompanyName(String companyName, String serviceProviderType) {
        ServiceProviderDTO query = new ServiceProviderDTO();
        query.setCompanyName(companyName);
        query.setServiceProviderType(serviceProviderType);
        return getServiceProvider(query);
    }

    @Override
    public ServiceProvider getByUscc(String uscc, String serviceProviderType) {
        ServiceProviderDTO query = new ServiceProviderDTO();
        query.setUscc(uscc);
        query.setServiceProviderType(serviceProviderType);
        return getServiceProvider(query);
    }

    @Override
    public ServiceProvider getEnableByUserId(Long userId, String serviceProviderType) {
        log.info("getEnableServiceProviderByUserId - 用户ID，服务商类型 查询有效的服务商注册信, userId={}, serviceProviderType={}",
                userId, serviceProviderType);
        ServiceProviderDTO query = new ServiceProviderDTO();
        query.setIsEnabled(BusinessConstant.ENABLE_YES);
        query.setUserId(userId);
        query.setServiceProviderType(serviceProviderType);
        return getServiceProvider(query);
    }

    @Override
    public ServiceProviderVO getServiceProviderVOByUserId(Long userId, String serviceProviderType) {
        log.info("getServiceProviderVOByUserId - 用户ID，服务商类型 查询服务商, userId={}, serviceProviderType={}",
                userId, serviceProviderType);
        ServiceProviderUser serviceProviderUser = serviceProviderUserService.getByUserId(userId, serviceProviderType);
        ServiceProvider serviceProvider;
        // 如果用户没有该类型的服务商，则查询用户在其他系统注册过的第一个服务商
        if (serviceProviderUser == null) {
            // 如果在其他系统也没有注册过服务商，则返回null，需要用户完善服务商的信息
            ServiceProvider firstServiceProvider = getFirstRegisterByUserId(userId);
            if (firstServiceProvider == null) {
                return null;
            }
            // 如果在其他系统注册过服务商，则复制服务商为本系统的服务商
            serviceProvider = copyNewTypeServiceProvider(firstServiceProvider, serviceProviderType);
            serviceProviderUser = serviceProviderUserService.getByUserId(userId, serviceProviderType);
        } else {
            serviceProvider = getById(serviceProviderUser.getServiceProviderId());
        }
        if (serviceProvider == null) {
            return null;
        }
        ServiceProviderVO serviceProviderVO = BeanUtil.toBean(serviceProvider, ServiceProviderVO.class);
        // 封装最新的审核结果
        ServiceProviderAudit audit = serviceProviderAuditService.getLatestAuditByServiceProviderId(serviceProviderVO.getId());
        if (audit == null) {
            return serviceProviderVO;
        }
        serviceProviderVO.setAuditType(audit.getAuditType().getCode());
        serviceProviderVO.setAuditTime(audit.getAuditTime());
        serviceProviderVO.setAuditOpinion(audit.getAuditOpinion());
        serviceProviderVO.setAuditUserId(audit.getAuditUserId());
        serviceProviderVO.setAuditUserName(audit.getAuditUserName());
        // 获取账号信息
        UserAccountVo userAccount = venueManageUserAccountService.findSimpleById(userId);
        serviceProviderVO.setUserAccountName(userAccount.getName());
        serviceProviderVO.setIsMainAccount(serviceProviderUser.getIsMainAccount());
        return serviceProviderVO;
    }

    @Override
    public ServiceProviderVO getServiceProviderVOById(Long id) {
        log.info("getServiceProviderVOById - id 查询服务商详情, id={}", id);
        ServiceProvider serviceProvider = getById(id);
        if (serviceProvider == null) {
            throw BizException.wrap(VenueServiceExceptionCode.SERVICE_PROVIDER_NOT_EXIST);
        }
        ServiceProviderVO serviceProviderVO = BeanUtil.toBean(serviceProvider, ServiceProviderVO.class);
        //查询投诉评价数量
        int count = evaluateComplaintService.getCountByServiceProviderId(id);
        serviceProviderVO.setServiceEvaluationCount(count);
        //查询不良记录数量
        List<ViolationRecordVO> list = violationRecordService.getViolationRecordListById(id);
        serviceProviderVO.setBadRecordCount(list.size());
        //信誉等级
        if (serviceProviderVO.getCreditScore() >= 0 && serviceProviderVO.getCreditScore() <= 59) {
            serviceProviderVO.setCreditLevel("D 一般");
        } else if (serviceProviderVO.getCreditScore() >= 60 && serviceProviderVO.getCreditScore() <= 80) {
            serviceProviderVO.setCreditLevel("C 良好");
        } else if (serviceProviderVO.getCreditScore() >= 81 && serviceProviderVO.getCreditScore() <= 94) {
            serviceProviderVO.setCreditLevel("B 优秀");
        } else {
            serviceProviderVO.setCreditLevel("A 极好");
        }
        return serviceProviderVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submitServiceProvider(ServiceProviderDTO serviceProviderDTO) {
        log.info("submitServiceProvider - 提交服务商信息, serviceProviderDTO={}", serviceProviderDTO);
        ServiceProvider existServiceProvider = getByUserId(serviceProviderDTO.getUserId(),
                serviceProviderDTO.getServiceProviderType());
        // 没有服务商信息则新增
        if (existServiceProvider == null) {
            saveServiceProvider(serviceProviderDTO);
            return true;
        }
        // 有服务商信息，且状态为已失效，则更新失效的服务商
        if (existServiceProvider.getIsEnabled().equals(BusinessConstant.ENABLE_NO)) {
            serviceProviderDTO.setId(existServiceProvider.getId());
            serviceProviderDTO.setRegisterTime(existServiceProvider.getRegisterTime());
            return updateDisableServiceProvider(serviceProviderDTO);
        }
        if (serviceProviderDTO.getId() == null) {
            throw BizException.validFail("该用户已绑定过服务商，不可新增");
        }
        // 更新有效的服务商
        return updateServiceProviderForAudit(serviceProviderDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceProvider saveServiceProvider(ServiceProviderDTO serviceProviderDTO) {
        log.info("saveServiceProvider - 保存服务商, serviceProviderDTO={}", serviceProviderDTO);
        return saveServiceProvider(serviceProviderDTO, true);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceProvider saveServiceProvider(ServiceProviderDTO serviceProviderDTO, boolean isAudit) {
        log.info("saveServiceProvider - 保存服务商, serviceProviderDTO={}, isAudit={}", serviceProviderDTO, isAudit);
        // 公司名称唯一
        if (getByCompanyName(serviceProviderDTO.getCompanyName(), serviceProviderDTO.getServiceProviderType()) != null) {
            throw BizException.wrap(VenueServiceExceptionCode.SERVICE_PROVIDER_COMPANY_NAME_EXIST);
        }
        // 统一社会信用代码唯一
        if (getByUscc(serviceProviderDTO.getUscc(), serviceProviderDTO.getServiceProviderType()) != null) {
            throw BizException.wrap(VenueServiceExceptionCode.SERVICE_PROVIDER_USCC_EXIST);
        }
        // 生成企业编码
        String companyCode = CreatCode.creatCode(baseMapper, COMPANY_CODE_FIELD, COMPANY_CODE_LENGTH, COMPANY_CODE_PREFIX);
        serviceProviderDTO.setCompanyCode(companyCode);
        // 保存服务商信息
        ServiceProvider serviceProvider = BeanUtil.toBean(serviceProviderDTO, ServiceProvider.class);
        save(serviceProvider);
        // 保存主用户与服务商关系
        ServiceProviderUserDTO serviceProviderUserDTO = new ServiceProviderUserDTO();
        serviceProviderUserDTO.setServiceProviderId(serviceProvider.getId());
        serviceProviderUserDTO.setServiceProviderType(serviceProvider.getServiceProviderType());
        serviceProviderUserDTO.setUserId(serviceProviderDTO.getUserId());
        serviceProviderUserDTO.setIsMainAccount(BusinessConstant.YES);
        serviceProviderUserService.saveServiceProviderUser(serviceProviderUserDTO);
        // 发起审核
        if (isAudit) {
            CopyOptions copyOptions = CopyOptions
                    .create()
                    .setIgnoreProperties(CommonConstants.COMMON_IGNORE_PROPERTIES);
            ServiceProviderAuditDTO auditDTO = BeanUtil.toBean(serviceProvider, ServiceProviderAuditDTO.class, copyOptions);
            auditDTO.setServiceProviderId(serviceProvider.getId());
            serviceProviderAuditService.saveServiceProviderAudit(auditDTO);
        }
        return serviceProvider;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateServiceProvider(ServiceProviderDTO serviceProviderDTO) {
        log.info("updateServiceProvider - 更新服务商基本信息, serviceProviderDTO={}", serviceProviderDTO);
        ServiceProvider serviceProvider = BeanUtil.toBean(serviceProviderDTO, ServiceProvider.class);
        return updateById(serviceProvider);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateServiceProviderForAudit(ServiceProviderDTO serviceProviderDTO) {
        log.info("updateServiceProvider - 更新服务商, serviceProviderDTO={}", serviceProviderDTO);
        // 申报中的服务商不可编辑
        ServiceProvider existServiceProvider = getById(serviceProviderDTO.getId());
        if (ServiceProviderAuditStatusEnum.REPORTING.eq(existServiceProvider.getAuditStatus())) {
            throw BizException.wrap(VenueServiceExceptionCode.SERVICE_PROVIDER_REPORTING_CAN_NOT_UPDATE);
        }
        // 公司名称唯一
        ServiceProvider byCompanyName = getByCompanyName(serviceProviderDTO.getCompanyName(), serviceProviderDTO.getServiceProviderType());
        if (byCompanyName != null && !byCompanyName.getId().equals(serviceProviderDTO.getId())) {
            throw BizException.wrap(VenueServiceExceptionCode.SERVICE_PROVIDER_COMPANY_NAME_EXIST);
        }
        // 统一社会信用代码唯一
        ServiceProvider byUscc = getByUscc(serviceProviderDTO.getUscc(), serviceProviderDTO.getServiceProviderType());
        if (byUscc != null && !byUscc.getId().equals(serviceProviderDTO.getId())) {
            throw BizException.wrap(VenueServiceExceptionCode.SERVICE_PROVIDER_USCC_EXIST);
        }
        if (ServiceProviderAuditStatusEnum.NOT_APPROVED.eq(existServiceProvider.getAuditStatus())) {
            // 更新审核拒绝的审核记录，重置审核信息
            serviceProviderDTO.setRegisterTime(existServiceProvider.getRegisterTime());
            serviceProviderAuditService.updateNotApprovedAudit(serviceProviderDTO);
            // 更新服务商信息，重置审核信息
            return updateServiceProviderReporting(serviceProviderDTO);
        }
        // 更新服务商信息，注意保留原有的审核信息
        ServiceProvider serviceProvider = getById(serviceProviderDTO.getId());
        CopyOptions copyOptions = CopyOptions
                .create()
                .setIgnoreProperties("auditStatus", "validStartTime", "validEndTime", "registerTime");
        BeanUtil.copyProperties(serviceProviderDTO, serviceProvider, copyOptions);
        // 重置cms同步状态
        serviceProvider.setCmsSync(BusinessConstant.NO);
        return updateById(serviceProvider);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateDisableServiceProvider(ServiceProviderDTO serviceProviderDTO) {
        // 公司名称唯一
        ServiceProvider byCompanyName = getByCompanyName(serviceProviderDTO.getCompanyName(), serviceProviderDTO.getServiceProviderType());
        if (byCompanyName != null && !byCompanyName.getId().equals(serviceProviderDTO.getId())) {
            throw BizException.wrap(VenueServiceExceptionCode.SERVICE_PROVIDER_COMPANY_NAME_EXIST);
        }
        // 统一社会信用代码唯一
        ServiceProvider byUscc = getByUscc(serviceProviderDTO.getUscc(), serviceProviderDTO.getServiceProviderType());
        if (byUscc != null && !byUscc.getId().equals(serviceProviderDTO.getId())) {
            throw BizException.wrap(VenueServiceExceptionCode.SERVICE_PROVIDER_USCC_EXIST);
        }
        // 发起新的审核
        CopyOptions auditCopyOptions = CopyOptions
                .create()
                .setIgnoreProperties(CommonConstants.COMMON_IGNORE_PROPERTIES);
        ServiceProviderAuditDTO auditDTO = BeanUtil.toBean(serviceProviderDTO, ServiceProviderAuditDTO.class, auditCopyOptions);
        auditDTO.setServiceProviderId(serviceProviderDTO.getId());
        serviceProviderAuditService.saveServiceProviderAudit(auditDTO);
        // 更新服务商信息，状态置为有效，审核状态置为申报中，保留注册时间
        return updateServiceProviderReporting(serviceProviderDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateServiceProviderReporting(ServiceProviderDTO serviceProviderDTO) {
        // 更新服务商基本信息
        ServiceProvider serviceProvider = getById(serviceProviderDTO.getId());
        CopyOptions copyOptions = CopyOptions
                .create()
                .setIgnoreProperties("registerTime");
        BeanUtil.copyProperties(serviceProviderDTO, serviceProvider, copyOptions);
        serviceProvider.setCmsSync(BusinessConstant.NO);
        updateById(serviceProvider);
        // 重置审核状态信息
        UpdateWrapper<ServiceProvider> updateWrapper = new UpdateWrapper<>();
        updateWrapper
                .lambda()
                .set(ServiceProvider::getIsEnabled, BusinessConstant.ENABLE_YES)
                .set(ServiceProvider::getAuditStatus, ServiceProviderAuditStatusEnum.REPORTING.getCode())
                .set(ServiceProvider::getValidStartTime, null)
                .set(ServiceProvider::getValidEndTime, null)
                .eq(ServiceProvider::getId, serviceProvider.getId())
        ;
        return update(updateWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAuditStatus(ServiceProviderAuditDTO auditDTO) {
        ServiceProvider serviceProvider = getById(auditDTO.getServiceProviderId());
        if (serviceProvider == null) {
            throw BizException.wrap(VenueServiceExceptionCode.SERVICE_PROVIDER_NOT_EXIST);
        }
        ServiceProviderAuditStatusEnum auditStateEnum
                = ServiceProviderAuditStatusEnum.get(auditDTO.getAuditResult().getCode());
        serviceProvider.setAuditStatus(auditStateEnum);
        serviceProvider.setValidStartTime(auditDTO.getValidStartTime());
        serviceProvider.setValidEndTime(auditDTO.getValidEndTime());
        return updateById(serviceProvider);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateServiceProviderDisableByType(String serviceProviderType) {
        log.info("updateServiceProviderDisableByType - 按照服务商类型更新服务商为已失效, serviceProviderType={}", serviceProviderType);
        // 查询过了有效期的服务商
        List<ServiceProvider> waitDisableList = listWaitingDisableServiceProviders(serviceProviderType);
        if (waitDisableList == null || waitDisableList.isEmpty()) {
            log.info("updateServiceProviderDisableByType - 没有要更新的服务商");
            return true;
        }
        // 更新用户为失效
        waitDisableList.forEach(serviceProvider -> serviceProvider.setIsEnabled(BusinessConstant.ENABLE_NO));
        return updateServiceProviderDisableByType(waitDisableList, serviceProviderType);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateServiceProviderDisableByType(List<ServiceProvider> list, String serviceProviderType) {
        // 更新用户为失效
        updateBatchById(list);
        // 解除角色
        // removeBatchServiceProviderRole(list, serviceProviderType);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCreditScore(ServiceProviderDTO serviceProviderDTO) {
        log.info("updateCreditScore - 更新服务商信用分值, serviceProviderDTO={}", serviceProviderDTO);
        ServiceProvider serviceProvider = getById(serviceProviderDTO.getId());
        if (serviceProvider == null) {
            // 这个值可能是场馆部门的ID，如果是部门ID则不能扣除服务商的分值
            return false;
        }
        int updateCreditScore = serviceProviderDTO.getCreditScore() == null ? 0 : serviceProviderDTO.getCreditScore();
        int creditScore = serviceProvider.getCreditScore() == null ? 0 : serviceProvider.getCreditScore();
        creditScore = creditScore + updateCreditScore;
        serviceProvider.setCreditScore(creditScore);
        return updateById(serviceProvider);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCreditScore(Long id, Integer score) {
        log.info("updateCreditScore - 更新服务商信用分值, id={}, score={}", id, score);
        ServiceProviderDTO serviceProviderDTO = new ServiceProviderDTO();
        serviceProviderDTO.setId(id);
        serviceProviderDTO.setCreditScore(score);
        return updateCreditScore(serviceProviderDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCrmHasSync(List<Long> ids) {
        log.info("updateCrmHasSync - 更新服务商crm同步状态为已同步, ids={}", ids);
        List<ServiceProvider> list = listByIds(ids);
        if (list == null || list.isEmpty()) {
            return false;
        }
        for (ServiceProvider serviceProvider : list) {
            serviceProvider.setCmsSync(BusinessConstant.YES);
            updateById(serviceProvider);
        }
        return true;
    }

    @Override
    public boolean addServiceProviderRole(String serviceProviderType, Long userId, Long serviceProviderId, String serviceProviderName) {
        // 添加角色
        ServiceProviderRoleEnum serviceProviderCommonRole = ServiceProviderService.getServiceProviderCommonRole(serviceProviderType);
        if (serviceProviderCommonRole == null) {
            throw BizException.wrap(VenueServiceExceptionCode.SERVICE_PROVIDER_TYPE_ERROR);
        }
        // 给配套服务商添加角色
        if (ServiceProviderRoleEnum.MATCHING_COMMON_ROLE.eq(serviceProviderCommonRole)) {
            return venueManageMatchingRegisterService.bindComplementServiceProviderRole(userId,
                    serviceProviderId, serviceProviderName, serviceProviderCommonRole.getCode());
        }
        // 给主场服务商添加角色
        if (ServiceProviderRoleEnum.HOME_COMMON_ROLE.eq(serviceProviderCommonRole)) {
            return venueManageHomeRegisterService.bindHomeServiceProviderRole(userId,
                    serviceProviderId, serviceProviderName, serviceProviderCommonRole.getCode());
        }
        // 给搭建服务商添加角色
        if (ServiceProviderRoleEnum.BUILD_COMMON_ROLE.eq(serviceProviderCommonRole)) {
            return venueManageBuilderRegisterService.bindBuilderServiceProviderRole(userId,
                    serviceProviderId, serviceProviderName, serviceProviderCommonRole.getCode());
        }
        // 给主运服务商添加角色
        if (ServiceProviderRoleEnum.MAIN_TRANSPORT_COMMON_ROLE.eq(serviceProviderCommonRole)) {
            return venueManageTransportRegisterService.bindServiceProviderRole(userId,
                    serviceProviderId, serviceProviderName, serviceProviderCommonRole.getCode());
        }
        return true;
    }

    @Override
    public boolean removeBatchServiceProviderRole(List<ServiceProvider> list, String serviceProviderType) {
        log.info("removeBatchServiceProviderRole - 批量移除服务商角色, serviceProviderType={}", serviceProviderType);
        // 解除角色
        ServiceProviderRoleEnum serviceProviderCommonRole = ServiceProviderService.getServiceProviderCommonRole(serviceProviderType);
        if (serviceProviderCommonRole == null) {
            throw BizException.wrap(VenueServiceExceptionCode.SERVICE_PROVIDER_TYPE_ERROR);
        }
        if (ServiceProviderRoleEnum.MATCHING_COMMON_ROLE.eq(serviceProviderCommonRole)) {
            return venueManageMatchingRegisterService.removeRole(list, serviceProviderCommonRole);
        }
        if (ServiceProviderRoleEnum.HOME_COMMON_ROLE.eq(serviceProviderCommonRole)) {
            return venueManageHomeRegisterService.removeRole(list, serviceProviderCommonRole);
        }
        if (ServiceProviderRoleEnum.BUILD_COMMON_ROLE.eq(serviceProviderCommonRole)) {
            return venueManageBuilderRegisterService.removeRole(list, serviceProviderCommonRole);
        }
        if (ServiceProviderRoleEnum.MAIN_TRANSPORT_COMMON_ROLE.eq(serviceProviderCommonRole)) {
            return venueManageTransportRegisterService.removeRole(list, serviceProviderCommonRole);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceProvider copyNewTypeServiceProvider(ServiceProvider sourceServiceProvider, String targetServiceProviderType) {
        log.info("copyNewTypeServiceProvider - 复制服务商, sourceServiceProvider={}, targetServiceProviderType={}",
                sourceServiceProvider, targetServiceProviderType);
        // 复制服务商
        CopyOptions copyOptions = CopyOptions
                .create()
                .setIgnoreProperties(CommonConstants.COMMON_IGNORE_PROPERTIES);
        ServiceProviderDTO serviceProviderDTO = BeanUtil.toBean(sourceServiceProvider, ServiceProviderDTO.class, copyOptions);
        serviceProviderDTO.setServiceProviderType(targetServiceProviderType);
        ServiceProvider newServiceProvider;
        try {
            newServiceProvider = saveServiceProvider(serviceProviderDTO, false);
        } catch (BizException e) {
            // 如果该类型服务商的公司名称或者统一社会性用代码已经存在，则该服务商已经被其他用户注册过，返回null
            if (VenueServiceExceptionCode.SERVICE_PROVIDER_COMPANY_NAME_EXIST.getCode() == e.getCode()
                    || VenueServiceExceptionCode.SERVICE_PROVIDER_USCC_EXIST.getCode() == e.getCode()) {
                return null;
            }
            throw e;
        }
        // 复制审核记录
        serviceProviderAuditService.copyBatchNewTypeServiceProviderAudit(sourceServiceProvider.getId(), newServiceProvider.getId(), targetServiceProviderType);
        if (sourceServiceProvider.getIsEnabled().equals(BusinessConstant.ENABLE_YES)
                && ServiceProviderAuditStatusEnum.APPROVED.eq(sourceServiceProvider.getAuditStatus())) {
            // 直接赋角色
            addServiceProviderRole(newServiceProvider.getServiceProviderType(), newServiceProvider.getUserId(), newServiceProvider.getId(), sourceServiceProvider.getCompanyName());
        }
        return newServiceProvider;
    }

    @Override
    public List<ExhibitionServiceProviderVO> queryNeedSyncExhibitionProvider() {
        return baseMapper.queryNeedSyncExhibitionProvider();
    }

    @Override
    public List<Long> queryServiceProviderIds(ServiceProviderDTO params) {
        QueryWrapper<ServiceProvider> queryWrapper = createServiceProviderVOQueryWrapper(params);
        return serviceProviderMapper.queryServiceProviderVOList(queryWrapper);
    }

    /**
     * 构建查询QueryWrapper
     *
     * @param query 查询参数
     * @return QueryWrapper
     */
    private QueryWrapper<ServiceProvider> createServiceProviderQueryWrapper(ServiceProviderDTO query) {
        QueryWrapper<ServiceProvider> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(ServiceProvider::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(query.getIsEnabled() != null, ServiceProvider::getIsEnabled, query.getIsEnabled())
                .eq(query.getAuditStatus() != null, ServiceProvider::getAuditStatus, query.getAuditStatus())
                .like(StrUtil.isNotBlank(query.getCompanyName()), ServiceProvider::getCompanyName, query.getCompanyName())
                .like(StrUtil.isNotBlank(query.getPrincipalName()), ServiceProvider::getPrincipalName, query.getPrincipalName())
                .like(StrUtil.isNotBlank(query.getLegalName()), ServiceProvider::getLegalName, query.getLegalName())
                .eq(StrUtil.isNotBlank(query.getServiceProviderType()), ServiceProvider::getServiceProviderType, query.getServiceProviderType())
                .eq(query.getUserId() != null, ServiceProvider::getUserId, query.getUserId())
                .in(query.getIds() != null && !query.getIds().isEmpty(), ServiceProvider::getId, query.getIds())
                .eq(query.getCmsSync() != null, ServiceProvider::getCmsSync, query.getCmsSync())
        ;
        return queryWrapper;
    }

    /**
     * 构建ServiceProviderVO的查询.
     *
     * @param query ServiceProviderDTO.
     * @return QueryWrapper.
     */
    private QueryWrapper<ServiceProvider> createServiceProviderVOQueryWrapper(ServiceProviderDTO query) {
        QueryWrapper<ServiceProvider> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("sp.is_deleted", BusinessConstant.DELETE_NO)
                .eq(query.getIsEnabled() != null, "sp.is_enabled", query.getIsEnabled())
                .eq(query.getAuditStatus() != null, "sp.audit_status", query.getAuditStatus())
                .like(StrUtil.isNotBlank(query.getCompanyName()), "sp.company_name", query.getCompanyName())
                .like(StrUtil.isNotBlank(query.getPrincipalName()), "sp.principal_name", query.getPrincipalName())
                .like(StrUtil.isNotBlank(query.getLegalName()), "sp.legal_name", query.getLegalName())
                .eq(StrUtil.isNotBlank(query.getServiceProviderType()), "sp.service_provider_type", query.getServiceProviderType())
                .eq(query.getUserId() != null, "sp.user_id", query.getUserId())
                .in(query.getIds() != null && !query.getIds().isEmpty(), "sp.id", query.getIds())
                .eq(query.getExhibitionManageId() != null, "em.id", query.getExhibitionManageId())
        ;
        return queryWrapper;
    }
}
